﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Core.h".
//-------------------------------------------------------------------

#ifndef _UXS_STATIC_STACK_H
#define _UXS_STATIC_STACK_H

#pragma once

#include "TStaticArray.h"

namespace UX_STL
{
namespace UXTypes
{

	//
	// Static Stack
	//

	#define TStaticStack	static_stack

	template <typename T, usize C, typename S = TCopyStrategy<T> >
	struct TStaticStack
	{
	// types
	public:
		typedef S						Strategy;
		typedef T						value_t;
		typedef uni_array<T>			uni_arr;
		typedef uni_array<const T>		uni_c_arr;
		typedef TStaticStack<T,C,S>		Self;


	// variables
	private:
		static_array<T,C,S>	_sArray;
		usize				_uPos;


	// methods
	public:
		TStaticStack () : _uPos(0) {}
		TStaticStack (const Self &other) : _sArray(other._sArray), _uPos(other._uPos) {}

		~TStaticStack () {}

		void		SetDefault (const T &tValue)	{ _sArray[0] = tValue; }
		
		bool		Pop ();
		bool		Push ();
		bool		Push (const T &tValue);

		T &			Get ()							{ return _sArray[_uPos]; }
		T const &	Get ()		  const				{ return _sArray[_uPos]; }

		T &			GetDefault ()					{ return _sArray[0]; }
		T const &	GetDefault () const				{ return _sArray[0]; }

		void		Set (const T &tValue)			{ _sArray.Set( _uPos, tValue ); }

		usize		Size()		const				{ return _sArray.Count(); }
		usize		Count()		const				{ return _uPos; }
		void		Clear()							{ _uPos = 0; }
		bool		Empty ()	const				{ return _uPos == 0; }
		
		operator		uni_arr ()					{ return _sArray.SubArray( 0, _uPos ); }
		operator const	uni_c_arr () const			{ return _sArray.SubArray( 0, _uPos ); }
	};



	template <typename T, usize C, typename S>
	inline bool TStaticStack<T,C,S>::Pop()
	{
		if ( _uPos > 0 ) {
			--_uPos;
			return true;
		}
		WARNING("stack is empty");
		return false;
	}

	
	template <typename T, usize C, typename S>
	inline bool TStaticStack<T,C,S>::Push()
	{
		if ( _uPos < _sArray.LastIndex() )
		{
			usize	u_last   = _uPos;
			_sArray[++_uPos] = _sArray[u_last];
			return true;
		}
		WARNING("stack overflow");
		return false;
	}

	
	template <typename T, usize C, typename S>
	inline bool TStaticStack<T,C,S>::Push(const T &tValue)
	{
		if ( _uPos < _sArray.LastIndex() )
		{
			_sArray[++_uPos] = tValue;
			return true;
		}
		WARNING("stack overflow");
		return false;
	}


#	undef TStaticStack

//-------------------------------------------------------------------

}	// UXTypes
}	// UX_STL

#endif	// _UXS_STATIC_STACK_H